package com.mes.cloud.utils;

import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/**
 * 文件上传
 */
public class FileUploadUtils {

    private static final Logger LOGGER = LoggerFactory.getLogger(FileUploadUtils.class);

    // 缓存大小
    static final int BUFFER = 2048;

    /**
     * 文件上传
     *
     * @param files 文件批量上传
     */
    public static Map<String, String> uploadFiles(MultipartFile[] files, String fileSavePath) {
        String suffix = null;
        String prefix = null;
        String newFileName = null;
        MultipartFile file = null;
        Map<String, String> map = new HashMap<>();
        try {
            for (int i = 0; i < files.length; i++) {
                file = files[i];
                long size = file.getSize();
                if (size <= 0) {
                    continue;
                }

                suffix = FilenameUtils.getExtension(file.getOriginalFilename());
                prefix = String.valueOf(new Date().getTime());
                newFileName = prefix + "." + suffix;

                String path = uploadFile(file, fileSavePath, newFileName);
                map.put(file.getOriginalFilename(), path);
            }
        } catch (Exception e) {
            LOGGER.debug("文件操作出现异常！");
        }
        return map;
    }

    public static String uploadFile(MultipartFile file, String fileSavePath) throws IOException {
        String suffix = FilenameUtils.getExtension(file.getOriginalFilename());
        String prefix = String.valueOf(DateUtil.getTimestamp().getTime());
        String newFileName = prefix + "." + suffix;
        uploadFile(file, fileSavePath, newFileName);
        return newFileName;
    }

    public static String uploadFile(MultipartFile file, String fileSavePath, String fileName) throws IOException {
        File saveDirectory = new File(fileSavePath);
        if (!saveDirectory.isDirectory()) {
            saveDirectory.mkdirs();
        }
        // 通过CommonsMultipartFile的方法直接写文件（注意这个时候）
        File newUploadFile = new File(saveDirectory, fileName);
        if (!newUploadFile.exists()) {
            newUploadFile.createNewFile();
        }
        FileOutputStream fileOutputStream = new FileOutputStream(newUploadFile);
        fileOutputStream.write(file.getBytes());
        String path = saveDirectory + "/" + fileName;
        return path;
    }

    /**
     * @param ins
     * @param file
     * @throws IOException
     * @Description: 把InputStream转成file
     * @author zhangkn
     * @date 2016年12月8日
     */
    private static void inputstreamToFile(InputStream ins, File file) throws IOException {
        OutputStream os = new FileOutputStream(file);
        int bytesRead = 0;
        byte[] buffer = new byte[8192];
        while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
            os.write(buffer, 0, bytesRead);
        }
        os.close();
        ins.close();
    }

    /**
     * @param file
     * @return
     * @throws IOException
     * @throws IllegalStateException
     * @Description: 上传zip压缩文件
     * @author xuzq01
     * @date 2017年4月14日
     */
    private String uploadZipFile(MultipartFile file, String fileSavePath, String date) throws IllegalStateException, IOException {
        // 文件保存路径
        String saveDirectoryPath = fileSavePath + date;
        LOGGER.info("上传保存目录：" + saveDirectoryPath);
        //将上传文件和解压文件保存在同一个目录里面
        File saveDirectory = new File(saveDirectoryPath);
        if (!saveDirectory.isDirectory()) {
            saveDirectory.mkdirs();
        }
        LOGGER.info("Project real path [" + saveDirectory.getAbsolutePath() + "]");
        String fileName = file.getOriginalFilename();

        // 通过CommonsMultipartFile的方法直接写文件（注意这个时候）
        File newUploadFile = new File(saveDirectory, fileName);
        file.transferTo(newUploadFile);
        //解压缩
        unZip(newUploadFile, saveDirectory.getPath());
        //删除原上传文件
        newUploadFile.delete();
        return fileName.substring(0, fileName.lastIndexOf("."));
    }

    /**
     * 解压文件操作
     *
     * @param file1 源文件对象
     * @param dest  解压的目标路径
     */
    @SuppressWarnings("rawtypes")
    public static void unZip(File file1, String dest) {
        try {
            ZipFile zipFile = new ZipFile(file1.getAbsolutePath());
            Enumeration emu = zipFile.entries();
            while (emu.hasMoreElements()) {
                ZipEntry entry = (ZipEntry) emu.nextElement();
                //会把目录作为一个file读出一次，所以只建立目录就可以，之下的文件还会被迭代到。
                if (entry.isDirectory()) {
                    new File(dest + File.separator + entry.getName().replace("\\", File.separator)).mkdirs();
                    continue;
                }
                BufferedInputStream bis = new BufferedInputStream(zipFile.getInputStream(entry));
                File file = new File(dest + File.separator + entry.getName().replace("\\", File.separator));
                //加入这个的原因是zipfile读取文件是随机读取的，这就造成可能先读取一个文件
                //而这个文件所在的目录还没有出现过，所以要建出目录来。
                File parent = file.getParentFile();
                if (parent != null && (!parent.exists())) {
                    boolean success = parent.mkdirs();
                    LOGGER.info("create folder {}", success);
                }
                FileOutputStream fos = new FileOutputStream(file);
                BufferedOutputStream bos = new BufferedOutputStream(fos, BUFFER);

                int count;
                byte[] data = new byte[BUFFER];
                while ((count = bis.read(data, 0, BUFFER)) != -1) {
                    bos.write(data, 0, count);
                }
                bos.flush();
                bos.close();
                bis.close();
                fos.close();
            }
            zipFile.close();
        } catch (Exception e) {
            LOGGER.error("", e);
        }
    }

    /**
     * 下载excel文件模板
     *
     * @param response
     * @param filePath
     * @param realFileName
     * @throws IOException
     */
    public static void downExcel(HttpServletResponse response,
                                 String filePath, String realFileName) throws IOException {
        // 设置响应类型和相应头
        response.setContentType("application/force-download");//应用程序强制下载
        response.setHeader("Content-Disposition", "attachment;filename="
                + URLEncoder.encode(realFileName,
                "UTF-8"));
        // 读取文件
        String realPath = filePath;
        InputStream in = new FileInputStream(realPath);
        response.setContentLength(in.available());

        // 复制模板信息
        OutputStream out = response.getOutputStream();
        byte[] b = new byte[1024];
        int len = 0;
        while ((len = in.read(b)) != -1) {
            out.write(b, 0, len);
        }
        out.flush();
        out.close();
        in.close();
    }
}
